package com.easybeanfit.UUService.commutill;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * <h3>错误拦截类</h3>
 *
 * @author Administrator 2012-12-2 上午1:58:37
 */
public class UUExceptionHandler implements UncaughtExceptionHandler {

    private static final String TAG = UUExceptionHandler.class.getSimpleName();
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    private static UUExceptionHandler INSTANCE;
    private Context context;
    // 用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();
    private boolean isSave = false;
    private String filename;
    private String fileDirs;

    private Handler handler = null;

    private HashMap<String, String> exceptionBean;

    /**
     * 获取拦截器的对象
     *
     * @author Administrator 2012-12-2 上午1:58:57
     * @param context
     * @return
     * @return UUExceptionHandler
     */
    public static UUExceptionHandler getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new UUExceptionHandler(context);
        }
        return INSTANCE;
    }

    /**
     * 如果需要在异常以后处理什么信息 请传入handler
     *
     * @author gdpancheng@gmail.com 2013-3-13 下午6:07:19
     * @param handler
     * @return void
     */
    public void SetHandler(Handler handler) {
        this.handler = handler;
    }

    /**
     * 设置是否保存日志文件 默认不保存 记得设置sd卡读取权限
     *
     * @author pancheng 2012-10-23 下午9:53:37
     * @param isSave
     * @return void
     */
    public void setSave(boolean isSave) {
        this.isSave = isSave;
    }

    /**
     * 当保存文件的前提下 设置文件名称 文件（名称-时间-毫秒数.log）
     *
     * @author pancheng 2012-10-23 下午9:54:04
     * @param filename
     * @return void
     */
    public void setFilename(String filename) {
        this.filename = filename;
    }

    /**
     * 当保存文件的前提下 设置保存目录 如/sdcard/logs/
     *
     * @author pancheng 2012-10-23 下午9:55:12
     * @param fileDirs
     * @return void
     */
    public void setFileDirs(String fileDirs) {
        this.fileDirs = fileDirs;
    }

    public UUExceptionHandler(Context context) {
        // 设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
        this.context = context;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        final String msg = collectDeviceInfo(context, ex);
        // Intent localIntent = new Intent(context, ExceptionActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // localIntent.putExtra("projectName", exceptionBean.get("projectName"));
        //
        // localIntent.putExtra("versionName", exceptionBean.get("versionName"));
        // localIntent.putExtra("versionCode", exceptionBean.get("versionCode"));
        // localIntent.putExtra("devInfo", exceptionBean.get("devInfo"));
        //
        // localIntent.putExtra("exceptionMsg", exceptionBean.get("exceptionMsg"));
        // context.startActivity(localIntent);
        if (handler != null) {
            Message message = new Message();
            message.obj = msg;
            handler.sendMessage(message);
        }
        System.out.println("错误：" + msg);
        if (isSave && filename != null && fileDirs != null) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    saveCrashInfoToFile(msg);
                }
            }).start();
        }

        // ex.printStackTrace();
        // android.os.Process.killProcess(android.os.Process.myPid());
    }

    /**
     * 收集设备参数信息
     *
     * @param ctx
     */
    private String collectDeviceInfo(Context ctx, Throwable ex) {
        exceptionBean = new HashMap<String, String>();
        exceptionBean.put("projectName", ctx.getApplicationInfo().loadLabel(ctx.getPackageManager()).toString());
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                exceptionBean.put("versionName", versionName);
                exceptionBean.put("versionCode", versionCode);
            }
        } catch (NameNotFoundException e) {
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
            }
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        exceptionBean.put("devInfo", sb.toString());

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        exceptionBean.put("exceptionMsg", result);
        return sb.toString();
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return 返回文件名称,便于将文件传送到服务器
     */
    private String saveCrashInfoToFile(String msg) {
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = filename + "-" + time + "-" + timestamp + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = fileDirs;
                if (!path.startsWith("/") || !path.endsWith("/")) {
                    Log.e(TAG, "the file path is err");
                    return null;
                }
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(msg.getBytes());
                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }

}
